/***********************************************************************************
 * 文件名： iac.c
 * 作者： 黄均铭
 * 版本： 1
 * 说明：
 *      智能雾化控制驱动程序。依据端口输入电压和占空比控制输出占空比，实现目标电压的输出。
 *      提供以下功能：
 *          启停；
 *          目标电压和超时设置；
 *          更多功能参考头文件中 API 说明。
 *      依赖 定时器计数 (超高频逆变器)。
 *      
 * 修改记录：
 * 	2021/03/16: 初版。 黄均铭。
***********************************************************************************/
#include "polsys.h"
#include "iac.h"



// 预定义 按时统计有效电压和去除旧累计值 积分时间片段 ms
#define IAC_TIME_INTEGRAL   30

// 预定义 有效电压补偿值
#define IAC_COMPENSATE  (0)

// 获取目标值分子 便于计算 (U^2 * 100) / R
#define IAC_GET_TARGET_FZ       (mIacRunParam.TargetVoltage + IAC_COMPENSATE) * (mIacRunParam.TargetVoltage + IAC_COMPENSATE) * 100;

//================================== 对外变量 =====================

//================================== 内部变量 =====================
static iac_run_param_t mIacRunParam = _IAC_RUN_PARAM_DEFAULT;
static u8 mTime;
static bool mAdcRun;
static volatile bool mAdcDoing;
static u16 mTimeout;
static pdata polsys_task_t mTask;         // 任务
static u32 mVxvx100;  // 目标有效电压的平方乘100 便于快速计算
static bool mIOState = true;   // IO口状态
//================================== 内部函数声明 =================
static void Task_Ica_Driver(void);
static void EvAdcUpdate(u16 result);

//================================== 对外函数接口 =================
// 上升沿事件（外部调用）
void Iac_EvPortRising(void)
{
    // 之前计数的是低电平
    Tim2_Stop();
    mIacRunParam.LowTime += Tim2_GetCnt();
    Tim2_SetCnt(0);
    Tim2_Run();
    if(mAdcRun && mAdcDoing == false)
    {
        mAdcDoing = true;
        Adc_Enable();
        Adc_StartOnce(ADC_CH_VREF, EvAdcUpdate);
    }
    mIOState = true;
}

// 下降沿事件（外部调用）
void Iac_EvPortFalling(void)
{
    Adc_Disable();
    // 之前计数的是高电平
    Tim2_Stop();
    mIacRunParam.HighTime += Tim2_GetCnt();
    Tim2_SetCnt(0);
    Tim2_Run();
    mAdcDoing = false;
    mIOState = false;
}



// 初始化。
// 注意需要先调用 Adc_Init 初始化ADC
void Iac_Init(void)
{
    mVxvx100 = IAC_GET_TARGET_FZ;
    mTime = 0;
    mAdcRun = false;
    mAdcDoing = false;
    
    // ADC初始化
    //Adc_Init();
    //Adc_Disable();
    // 计数定时器
    Tim2_Init();
    
    // 注册任务
    Polsys_TaskInit(&mTask, Task_Ica_Driver, 1);
}

// 开始工作，启动输出。
void Iac_Start(void)
{
    mAdcRun = true;
    mIacRunParam.Running = true;
    mTimeout = 0;
    // mos管控制脚 默认开启
    _IAC_OUT_ENABLE;
    // 启动计数
    Tim2_SetCnt(0);
    Tim2_Run();
}

// 停止输出。
void Iac_Stop(void)
{
    mIacRunParam.Running = false;
    Tim2_Stop();
}

// 设置目标电压。
void Iac_SetTargetVolatge(u16 mv)
{
    if(mIacRunParam.TargetVoltage == mv)return;
    mIacRunParam.TargetVoltage = mv;
    mVxvx100 = IAC_GET_TARGET_FZ;
}

// 设置超时时间。
void Iac_SetTimeout(u16 ms)
{
    mIacRunParam.TargetTime = ms;
}

// 是否正在运行。
bool Iac_IsRun(void)
{
    return mIacRunParam.Running;
}

// 获取运行参数（返回结构体指针）。
iac_run_param_t *Iac_GetRunParam(void)
{
    return &mIacRunParam;
}

//================================== 内部函数实现 =================

// ADC中断事件
static void EvAdcUpdate(u16 result)
{
    u16 adc = result;
    if(mAdcRun && mAdcDoing)
    {
        // 转换完成之后必须还是高电平
        if(adc < 2200)
        {
            mAdcRun = false;
            mIacRunParam.HighVoltage = (u16)((u32)1200*ADC_FULL_VALUE/adc) + 110;
        //    mIacRunParam.HighVoltage += (mIacRunParam.HighVoltage)/10; // 3200 140 1.73   3800 140 1.77
        }
    }
    mAdcDoing = false;
    Adc_Disable();
}


// 任务 1ms调用
static void Task_Ica_Driver(void)
{
    u16 adc;
    if(mIacRunParam.Running == false) return;

    // 统计高低电平
    Tim2_Stop();
    if(_IAC_GET_OUT_LEVEL)
    {
        mIacRunParam.HighTime += Tim2_GetCnt();
//        if(mAdcRun && mAdcDoing)
//        {
//            // 启动ADC
//            adc = Adc_GetOnce(ADC_CH_VREF);
//            // 转换完成之后必须还是高电平
//            if(mAdcDoing && adc < 2200)
//            {
//                mAdcRun = false;
//                mIacRunParam.HighVoltage = ADC_FULL_VALUE * 1200 / adc + 180;
//            }
//        }
//        mAdcDoing = true;
    }
    else
    {
        mIacRunParam.LowTime += Tim2_GetCnt();
    }
    Tim2_SetCnt(0);
    Tim2_Run();
    // 根据比例判断是否开启mos管  当前比例: h / (h + l)  目标比例: NowDuty / 100
    if((mIacRunParam.HighTime) * 100 > (mIacRunParam.HighTime + mIacRunParam.LowTime) * mIacRunParam.TargetDuty) _IAC_OUT_DISABLE;
    else _IAC_OUT_ENABLE;
    // 运行时计算比例
    mTime++;
    if(mTime >= IAC_TIME_INTEGRAL)
    {
        mTime = 0;
        mAdcRun = true;
        
        // 统计输出时间
        mTimeout += IAC_TIME_INTEGRAL;
        if(mTimeout >= mIacRunParam.TargetTime)
        {
            // 关闭输出 结束
            _IAC_OUT_DISABLE;
            mIacRunParam.Running = false;
            return;
        }
        
        // 当前比例
        mIacRunParam.NowDuty = mIacRunParam.HighTime * 100 / (mIacRunParam.HighTime + mIacRunParam.LowTime);
        
        // 根据目标电压和实时电压计算目标pwm   NowDuty = (Ut / Um)^2 * 100    +1补偿
        mIacRunParam.TargetDuty = mVxvx100 / ((u32)mIacRunParam.HighVoltage * mIacRunParam.HighVoltage)  + 0;
        // 高电平 100%
        if(mIOState && mAdcDoing == false && mIacRunParam.TargetDuty >= 100)
        {
            mAdcDoing = true;
            Adc_Enable();
            Adc_StartOnce(ADC_CH_VREF, EvAdcUpdate);
        }
    
        // 积分清除部分累计值 100比例 保持小段电压稳定
        mIacRunParam.HighTime = mIacRunParam.NowDuty*512;
        mIacRunParam.LowTime = 51200 - mIacRunParam.NowDuty*512;
    }
}

//================================== 结束 ========================
